package org.example.traceability.service;

import java.lang.Exception;
import java.lang.String;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.traceability.model.bo.traceabilityAddProductInputBO;
import org.example.traceability.model.bo.traceabilityAddUserByAdminInputBO;
import org.example.traceability.model.bo.traceabilityDisableUserInputBO;
import org.example.traceability.model.bo.traceabilityProductsInputBO;
import org.example.traceability.model.bo.traceabilityQueryProductInputBO;
import org.example.traceability.model.bo.traceabilityRegisterUserInputBO;
import org.example.traceability.model.bo.traceabilityUpdateProductInputBO;
import org.example.traceability.model.bo.traceabilityUpdateUserInputBO;
import org.example.traceability.model.bo.traceabilityUsersInputBO;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
@NoArgsConstructor
@Data
public class traceabilityService {
  public static final String ABI = org.example.traceability.utils.IOUtil.readResourceAsString("abi/traceability.abi");

  public static final String BINARY = org.example.traceability.utils.IOUtil.readResourceAsString("bin/ecc/traceability.bin");

  public static final String SM_BINARY = org.example.traceability.utils.IOUtil.readResourceAsString("bin/sm/traceability.bin");

  @Value("${system.contract.traceabilityAddress}")
  private String address;

  @Autowired
  private Client client;

  AssembleTransactionProcessor txProcessor;

  @PostConstruct
  public void init() throws Exception {
    this.txProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(this.client, this.client.getCryptoSuite().getCryptoKeyPair());
  }

  public CallResponse productCount() throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "productCount", Arrays.asList());
  }

  public CallResponse products(traceabilityProductsInputBO input) throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "products", input.toArgs());
  }

  public CallResponse userCount() throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "userCount", Arrays.asList());
  }

  public TransactionResponse updateProduct(traceabilityUpdateProductInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "updateProduct", input.toArgs());
  }

  public TransactionResponse updateUser(traceabilityUpdateUserInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "updateUser", input.toArgs());
  }

  public TransactionResponse addUserByAdmin(traceabilityAddUserByAdminInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "addUserByAdmin", input.toArgs());
  }

  public TransactionResponse queryProduct(traceabilityQueryProductInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "queryProduct", input.toArgs());
  }

  public CallResponse users(traceabilityUsersInputBO input) throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "users", input.toArgs());
  }

  public TransactionResponse disableUser(traceabilityDisableUserInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "disableUser", input.toArgs());
  }

  public TransactionResponse addProduct(traceabilityAddProductInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "addProduct", input.toArgs());
  }

  public TransactionResponse registerUser(traceabilityRegisterUserInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "registerUser", input.toArgs());
  }
}
